Linux驱动开发常用调试工具 您所在的位置:网站首页 物理内存68 Linux驱动开发常用调试工具

Linux驱动开发常用调试工具

2023-09-10 16:00| 来源: 网络整理| 查看: 265

问题

这段时间实验室要完成一个内存故障注入工具和寄存器故障注入工具,在编写驱动的过程中,调试起来很麻烦(一般都是printk打印出来的,调试起来太不方便),于是想

“可不可以在调试设备驱动的时候,利用一个小工具来读写内存某块区域的值以及CPU中寄存器的值?

这点前辈的大神已经为我们找到了,参见《LDD3》的《第十五章 内存映射和DMA》

目前已经有这样的工具了devmem和devkmem,就是通过mmap映射/dev/mem的。

这个工具的源码简单,google一下到处都是,这里随便给出一两个地址: http://sources.buildroot.net/devmem2.c https://dev.openwrt.org/browser/packages/utils/devmem2/src/devmem2.c

/dev/mem和/dev/kmem其实是在同一个驱动中代码中产生的:drivers/char/mem.c

如果想知道具体的情况,建议大家认真学习《LDD3》的《第十五章 内存映射和DMA》,然后自己分析源码。

Linux下/dev/mem和/dev/kmem的区别

/dev/mem: 物理内存的全镜像。可以用来访问物理内存。

用来访问物理IO设备,比如X用来访问显卡的物理内存,或嵌入式中访问GPIO。用法一般就是open,然后mmap,接着可以使用map之后的地址来访问物理内存。这其实就是实现用户空间驱动的一种方法。

/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。 一般可以用来查看kernel的变量,或者用作rootkit之类的。 devmem 使用 Usage: ./devmem { address } [ type [ data ] ] address : memory address to act upon type : access operation type : [b]yte, [h]alfword, [w]ord data : data to be written 1 2 3 4 1 2 3 4 参数 描述 address 物理地址,如果是要修改该地址的数据,需要填入下面的参数;如果只是读取,省略即可 type 要访问的数据类型 [b]yte, [h]alfword, [w]ord data 想要写入的数据

通过使用,发现IO内存和物理内核都可以读写。

源码 /* * devmem2.c: Simple program to read/write from/to any location in memory. * * Copyright (C) 2000, Jan-Derk Bakker ([email protected]) * * * This software has been developed for the LART computing board * (http://www.lart.tudelft.nl/). The development has been sponsored by * the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/) * and Ubiquitous Communications (http://www.ubicom.tudelft.nl/) * projects. * * The author can be reached at: * * Jan-Derk Bakker * Information and Communication Theory Group * Faculty of Information Technology and Systems * Delft University of Technology * P.O. Box 5031 * 2600 GA Delft * The Netherlands * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include #include #include #include #define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \ __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0) #define MAP_SIZE 4096UL #define MAP_MASK (MAP_SIZE - 1) int main(int argc, char **argv) { int fd; void *map_base, *virt_addr; unsigned long read_result, writeval; off_t target; int access_type = 'w'; if(argc < 2) { fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n" "\taddress : memory address to act upon\n" "\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n" "\tdata : data to be written\n\n", argv[0]); exit(1); } target = strtoul(argv[1], 0, 0); if(argc > 2) access_type = tolower(argv[2][0]); if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL; printf("/dev/mem opened.\n"); fflush(stdout); /* Map one page */ map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK); if(map_base == (void *) -1) FATAL; printf("Memory mapped at address %p.\n", map_base); fflush(stdout); virt_addr = map_base + (target & MAP_MASK); switch(access_type) { case 'b': read_result = *((unsigned char *) virt_addr); break; case 'h': read_result = *((unsigned short *) virt_addr); break; case 'w': read_result = *((unsigned long *) virt_addr); break; default: fprintf(stderr, "Illegal data type '%c'.\n", access_type); exit(2); } printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result); fflush(stdout); if(argc > 3) { writeval = strtoul(argv[3], 0, 0); switch(access_type) { case 'b': *((unsigned char *) virt_addr) = writeval; read_result = *((unsigned char *) virt_addr); break; case 'h': *((unsigned short *) virt_addr) = writeval; read_result = *((unsigned short *) virt_addr); break; case 'w': *((unsigned long *) virt_addr) = writeval; read_result = *((unsigned long *) virt_addr); break; } printf("Written 0x%X; readback 0x%X\n", writeval, read_result); fflush(stdout); } if(munmap(map_base, MAP_SIZE) == -1) FATAL; close(fd); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 devkmem

在后来的模块调试中,有一次需要查看内核虚拟地址中的数据,我又想起了“/dev/kmem”,

使用

使用方法: 用法: devkmem { address }

参数 描述 address 虚拟地址(内核逻辑地址) 源码

(仅支持读取)内核虚拟地址中的数据。

#include #include #include #include #include #include #include #include #define DEVKMEM "/dev/kmem" #define PAGE_SIZE 0x1000 #define PAGE_MASK (~(PAGE_SIZE-1)) int main(int argc, char* argv[]) { int fd; char *mbase; char read_buf[10]; unsigned int regAddr; unsigned int varAddr; varAddr = strtoul(argv[1], 0, 16); unsigned int ptr = varAddr & ~(PAGE_MASK); fd = open(DEVKMEM, O_RDONLY); if (fd == -1) { perror("open"); exit(-1); } mbase = mmap(0,PAGE_SIZE,PROT_READ,MAP_SHARED,fd, (varAddr & PAGE_MASK)); if (mbase == MAP_FAILED) { printf("map failed %s\n",strerror(errno)); } printf("varAddr = 0x%X \n", varAddr); printf("mapbase = 0x%X \n", (unsigned int)mbase); printf("value = 0x%X \n",*(unsigned int*)(mbase+ptr)); printf("char = %c%c%c%c \n", *(char *)(mbase+ptr), *(char *)(mbase+ptr+1), *(char *)(mbase+ptr+2), *(char *)(mbase+ptr+3)); close(fd); munmap(mbase,PAGE_SIZE); return 0; }

转载:http://blog.csdn.net/gatieme/article/details/50964903



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有